package com.ttg.web.juc;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.ttg.common.annotation.TaskRunMethod;
import com.ttg.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class TasktemplateHelper<T, P> {
    @Autowired(required = false)
    private ListeningExecutorService executorService;
    private ConcurrentHashMap<Object, TargetWarpper> concurrentHashMap = new ConcurrentHashMap<>();

    public ListenableFuture submit(T t,P... p) {
        TargetWarpper targetWarpper = concurrentHashMap.get(t);
        if (Objects.isNull(targetWarpper)) {
            targetWarpper=init(t,p);
        }
        if(!targetWarpper.getIsEnable()){
            return  null;
        }
        ListenableFutureTaskTemp futureTask = new ListenableFutureTaskTemp(targetWarpper, p);
        return executorService.submit(futureTask);
    }

    private TargetWarpper init(T t, P... p) {
        synchronized (t) {
            TargetWarpper targetWarpper;
            if (Objects.nonNull(targetWarpper = concurrentHashMap.get(t))) {
                return targetWarpper;
            }
            targetWarpper = new TargetWarpper();
            TaskRunMethod taskRunMethod = null;
            String methodName = null;
            targetWarpper.setT(t);
            concurrentHashMap.put(t, targetWarpper);
            if (Objects.isNull(taskRunMethod = t.getClass().getAnnotation(TaskRunMethod.class))
                    || (StringUtils.isBlank(methodName = StringUtil.trim(taskRunMethod.value())))) {
                log.error(t.getClass().getName() + "要有@TaskRunMethod注解并要需要回调方法名");
                targetWarpper.setErrMsg(t.getClass().getName() + "要有@TaskRunMethod注解并要需要回调方法名");
                return targetWarpper;
            }
            Class<?>[] classes = new Class[p.length];//遍历获取对应的参数类型并装入
            for (int i = 0; i < p.length; i++) {
                if (Objects.isNull(p[i])) {
                    log.error(t.getClass().getName() + "异步调用方法传入的第" + (i + 1) + "参数为空");
                    targetWarpper.setErrMsg(t.getClass().getName() + "异步调用方法传入的第" + (i + 1) + "参数为空");
                    return targetWarpper;
                }
                classes[i] = p[i].getClass();
            }
            try {
                Method method = t.getClass().getDeclaredMethod(methodName, classes);
                targetWarpper.setMethod(method);
            } catch (NoSuchMethodException e) {
                log.error("反射获取方法异常:" + e.getMessage());
                targetWarpper.setErrMsg("反射获取方法异常:" + e.getMessage());
                return targetWarpper;
            }
            targetWarpper.setIsEnable(true);
            return targetWarpper;
        }
    }
    public Boolean getTargetStatus(T t){//获取 启用标识
        return  concurrentHashMap.get(t).getIsEnable();
    };
    public String getTargetErrMsg(T t){//获取 启用标识
        return  concurrentHashMap.get(t).getErrMsg();
    };

}

 